package main

// @title devopsapi
// @version v1.1
// @description 安全运维中心API接口
// @termsOfService https://weiyigeek.top/terms

// @contact.name 开发者【WeiyiGeek】
// @contact.url http://weiyigeek.top/support
// @contact.email master@weiyigeek.top

// @externalDocs.description  DevOpsApi 外部文档的描述
// @externalDocs.url          https://swagger.io/resources/open-api/

// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html

// @host      10.20.172.106:8080
// @BasePath  /api/v1

// @schemes http https

// @securityDefinitions.basic	BasicAuth
// $ echo -n weiyigeek:123456 | base64
// d2VpeWlnZWVrOjEyMzQ1Ng==

//	@securityDefinitions.apikey	API鉴权
//	@in							header
//	@name						Authorization
//	@description				Description for what is this security definition being used

import (
	"context"
	"devopsapi/middleware"
	"devopsapi/pkg/global"
	"devopsapi/pkg/util/emails"
	router "devopsapi/routers"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/gin-gonic/gin"
	"gopkg.in/tylerb/graceful.v1"
)

// init 初始化项目配置以及数据库连接池
func init() {
	global.SetupConfig("prod")
	emails.NewEmailer()
}

func main() {
	// 指定 gin 运行模式
	gin.SetMode(global.App.Mode)

	// 返回一个新的空白Engine实例
	r := gin.New()

	// 设置日志中间件
	r.Use(middleware.Logger())

	// 加载自定义路由
	router.Load(r)

	// 使用 graceful 管理 Gin 服务从而优雅的停止
	srv := &graceful.Server{
		Timeout: 10 * time.Second,
		Server: &http.Server{
			// Gin运行的监听端口
			Addr: fmt.Sprintf("%s:%d", global.App.Host, global.App.Port),
			// 要调用的处理程序，http.DefaultServeMux如果为nil
			Handler: r,
			// MaxHeaderBytes控制服务器解析请求标头的键和值（包括请求行）时读取的最大字节数 (通常情况下不进行设置)
			MaxHeaderBytes: 1 << 20,
		},
	}

	// 开启一个goroutine启动服务 启动 HTTP Server
	go func() {
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("listen: %s\n", err)
		}
	}()

	// 在一个新的goroutine中调用给定的函数
	// 等待中断信号
	quit := make(chan os.Signal)
	// kill 默认会发送 syscall.SIGTERM 信号
	// kill -2 发送 syscall.SIGINT 信号，我们常用的Ctrl+C就是触发系统SIGINT信号
	// kill -9 发送 syscall.SIGKILL 信号，但是不能被捕获，所以不需要添加它
	// signal.Notify把收到的 syscall.SIGINT或syscall.SIGTERM 信号转发给quit
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) // 此处不会阻塞
	<-quit                                               // 阻塞在此，当接收到上述两种信号时才会往下执行
	log.Println("Shutdown Server ...")

	// 创建一个 5 秒的超时上下文
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	// 关闭 HTTP Server
	// 	// 5秒内优雅关闭服务（将未处理完的请求处理完再关闭服务），超过5秒就超时退出
	if err := srv.Shutdown(ctx); err != nil {
		log.Fatal("Server Shutdown:", err)
	}
	log.Println("Server exiting")
}
